package com.gitee.wsl.flow.create

import com.gitee.wsl.data.savable.SavableHandler
import com.gitee.wsl.flow.F
import kotlinx.coroutines.flow.MutableStateFlow
import kotlin.reflect.KType
import kotlin.reflect.typeOf


inline fun <reified T> SavableHandler.savableFlow(
    key: String,
    initialValue: T
): MutableStateFlow<T> {
    return savableFlow(
        key = key,
        initialValueProvider = { initialValue },
        saveType = typeOf<T>(),
        saveTypeMapper = { it },
        restoreTypeMapper = { it }
    )
}

inline fun <reified T> F.savableFlow(
    key: String,
    initialValue: T,
    savableHandler: SavableHandler
) = savableHandler.savableFlow(key, initialValue)

inline fun <T, reified S> SavableHandler.savableFlow(
    key: String,
    noinline initialValueProvider: () -> T,
    noinline saveTypeMapper: (T) -> S,
    noinline restoreTypeMapper: (S) -> T
): MutableStateFlow<T> {
    return savableFlow(
        key = key,
        initialValueProvider = initialValueProvider,
        saveType = typeOf<S>(),
        saveTypeMapper = saveTypeMapper,
        restoreTypeMapper = restoreTypeMapper
    )
}

inline fun <T, reified S> F.savableFlow(
    key: String,
    savableHandler: SavableHandler,
    noinline initialValueProvider: () -> T,
    noinline saveTypeMapper: (T) -> S,
    noinline restoreTypeMapper: (S) -> T
) = savableHandler.savableFlow(key, initialValueProvider, saveTypeMapper, restoreTypeMapper)

fun <T, S> SavableHandler.savableFlow(
    key: String,
    initialValueProvider: () -> T,
    saveType: KType,
    saveTypeMapper: (T) -> S,
    restoreTypeMapper: (S) -> T
): MutableStateFlow<T> {
    val savedState = getSaved<S>(key, saveType)
    val state: MutableStateFlow<T> = if (savedState != null) {
        MutableStateFlow(restoreTypeMapper(savedState))
    } else {
        MutableStateFlow(initialValueProvider())
    }
    setSaver(key, saveType) { saveTypeMapper(state.value) }
    return state
}

fun <T, S> F.savableFlow(
    key: String,
    savableHandler: SavableHandler,
    initialValueProvider: () -> T,
    saveType: KType,
    saveTypeMapper: (T) -> S,
    restoreTypeMapper: (S) -> T
) = savableHandler.savableFlow(key, initialValueProvider, saveType, saveTypeMapper, restoreTypeMapper)